//==================================================
// D_NC_temp_stepper.ino
// 2015-04-02
//==================================================
// Nabton Client Generic Configuration
//==================================================

// Adjust these paramaters acording to specific application
#define NFLOAT 2  // No of decimals i float value
#define SIDN  5   // No of SIDs
#define SID1 901  // Temp 1
#define SID2 902  // Temp 2
#define SID3 903  // Temp 3
#define SID4 904  // Temp 4
#define SID5 905  // Stepper
#define SID6 906
#define SID7 907
#define SID8 908

// Fixed part of configuration

// Arduino states
#define YES_SYNC 1
#define NO_SYNC  2
#define MAX_SID 10
#define MAX_ORDERS 100
#define PIN_LED_STATUS 3
int g_sids[10] = {SIDN,SID1,SID2,SID3,SID4,SID5,SID6,SID7,SID8};
unsigned long g_time1=0,g_time2=0,g_delta,g_now, g_last[MAX_SID];
unsigned long g_one_sec = 1000; // resolution of heartbeat =  1000 msec
int g_on[MAX_ORDERS];    // Arduino - RPi interface par type
int g_value[MAX_ORDERS]; // Arduino - RPi interface par value
int g_sidHb[MAX_SID];
int g_sidHbUnit[MAX_SID];
int g_sidDelay[MAX_SID]; // Always in sec
int g_sidCountDown[MAX_SID];
char g_errmsg[120];  // Error message
int g_error = 0;     // Error flag
char g_logmsg[120];  // Log message
int g_log = 0;       // Log flag
int g_state = NO_SYNC; 
char g_res[120];
int g_counter = 0;
int g_device_delay = 1000;

// Arduino-RPi protocol
#define NABTON_DATA     1 
#define NABTON_INFO     2
#define NABTON_NODATA   3
#define NABTON_LOG      8 
#define NABTON_ERROR    9 
// Arduino Control Protocol
#define ON_DELAY_VAL     2
#define ON_DELAY_UNIT    3
#define ON_STEPPER_DIR   4
#define ON_STEPPER_STEPS 5
#define ON_STEPPER_SPEED 6

#define ERR_SID_NOT_FOUND  "SID_not_found"
#define ERR_UNSUPPORTED_MESSAGE "Unsupported_message"
#define ERR_NO_MESSAGE "No_message"
#define ERR_SID_MISMATCH "SID_Mismatch"
//=================================================
//
// D0 RX used for serial communication to server (Raspberry Pi)
// D1 TX used for serial communication to server (Raspberry Pi)
// D2
// D3 Message Pin (blink led)
// D4 IR Data
// D5
// D6 DIR Stepper
// D7 STEP Stepper
// D8 SLEEP Stepper
// D9 One Wire Data
// D10  RX Bluetooth device
// D11  TX Bluetooth device
// D12 
// D13
//
// A0
// A1
// A2
// A3
// A4 SDA I2C OLED
// A5 SCL I2C OLED

// MEGA
// D20 SDA I2C OLED
// D21 SCL I2C OLED
//=================================================
//==================================================
// Nabton Client Application Configuration
//==================================================
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SoftwareSerial.h>
//#include <IRremote.h>
#include <U8glib.h>

#define NC_NAME "D1.0"
//=================================================
// One Wire
//=================================================

#define ONE_WIRE_BUS 9
#define TEMPERATURE_PRECISION 12
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress device[MAX_SID];
int nsensors = 0;
//==================================================
// Stepper Motor
//==================================================
int DIR   = 6; 
int STEP  = 7;
int SLEEP = 8;
//==================================================
// OLED I2C
//==================================================

//U8GLIB_SSD1306_128X64 u8g(13, 11, 10, 9);// SW SPI protocol(4 pins): SCK = 13, MOSI = 11, CS = 10, A0 = 9	
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // Small display I2C protocol (2 pins)
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE); // Large display
char dl[5][8],dm[5][8],dr[5][8];
//=================================================
void NB_oledDraw() 
//=================================================
{
 u8g.firstPage();  
  do {
        draw();
  } while( u8g.nextPage() ); 
}
//================================================
void stepCW(int steps,int dd)
//================================================
{
  int i;
  digitalWrite(DIR, LOW);   
  digitalWrite(SLEEP, HIGH); // Set the Sleep mode to AWAKE.
  for(i=0;i<=steps;i++)
    {
      delayMicroseconds(200);
      digitalWrite(STEP, HIGH); 
      //delay(dd);     
      digitalWrite(STEP, LOW);
      delay(dd);  
    }  
  digitalWrite(DIR, LOW);   
  digitalWrite(SLEEP, LOW); // Set the Sleep mode to SLEEP.   
}

//================================================
void stepCCW(int steps,int dd)
//================================================
{
  int i;
  digitalWrite(DIR, HIGH);                 
  digitalWrite(SLEEP, HIGH); // Set the Sleep mode to AWAKE.
  for(i=0;i<=steps;i++)
    {
      delayMicroseconds(200);
      digitalWrite(STEP, HIGH);   
      //delay(dd);       
      digitalWrite(STEP, LOW); 
      delay(dd);     
    }  
  digitalWrite(DIR, LOW);   
  digitalWrite(SLEEP, LOW); // Set the Sleep mode to SLEEP.    
}
//=================================================
void draw()
//=================================================
{
  // Horizontal pixels: 0 - 120
  // Vertical pixels: 0 - 63
  //u8g.setFont(u8g_font_6x10);
  u8g.setFont(u8g_font_unifont);
  //u8g.setFont(u8g_font_osb21);
  /*u8g.drawStr( 0, 1, ".....");
  u8g.drawStr( 45, 1, ".....");
  u8g.drawStr( 90, 1, ".....");
  
  u8g.drawStr( 0, 63, "_____");
  u8g.drawStr( 45,63, "_____");
  u8g.drawStr( 90,63, "_____");*/
  
  u8g.drawStr( 0, 10, dl[1]);
  u8g.drawStr( 0, 27, dl[2]);
  u8g.drawStr( 0, 45, dl[3]);
  u8g.drawStr( 0, 62, dl[4]);

  u8g.drawStr( 45, 10, dm[1]);
  u8g.drawStr( 45, 27, dm[2]);
  u8g.drawStr( 45, 45, dm[3]);
  u8g.drawStr( 45, 62, dm[4]);

  u8g.drawStr( 90, 10, dr[1]);
  u8g.drawStr( 90, 27, dr[2]);
  u8g.drawStr( 90, 45, dr[3]);
  u8g.drawStr( 90, 62, dr[4]);  

}
//=================================================
void NB_serialFlush()
//=================================================
{
  //Serial.print("flush:"); 
  while(Serial.available() > 0) {
    char t = Serial.read();
    //Serial.print(t); 
  }
  //Serial.println(":flushed"); 
}   
//=================================================
void NB_printFloat(float value, int places) 
//=================================================
{
  int digit;
  float tens = 0.1;
  int tenscount = 0;
  int i;
  float tempfloat = value;
  float d = 0.5;
  
  if (value < 0) d *= -1.0;
  for (i = 0; i < places; i++) d/= 10.0;    
  tempfloat +=  d;
  if (value < 0) tempfloat *= -1.0;
  while ((tens * 10.0) <= tempfloat) 
  {
    tens *= 10.0;
    tenscount += 1;
  }
  if (value < 0) Serial.print('-');
  if (tenscount == 0) Serial.print(0, DEC);
  for (i=0; i< tenscount; i++) 
  {
    digit = (int) (tempfloat/tens);
    Serial.print(digit, DEC);
    tempfloat = tempfloat - ((float)digit * tens);
    tens /= 10.0;
  }
  if (places <= 0) return;
  Serial.print('.');  
  for (i = 0; i < places; i++) 
  {
    tempfloat *= 10.0; 
    digit = (int) tempfloat;
    Serial.print(digit,DEC);  
    tempfloat = tempfloat - (float) digit; 
  }
}

//=================================================
void NB_sendToGwy(int mid, int sid, float data, int other)
//=================================================
{
  int ixSid = 0,i,checksum;
  char msg[120];

     digitalWrite(PIN_LED_STATUS,HIGH);
     Serial.print("*");
     Serial.print(mid);Serial.print(" "); 
     Serial.print(sid);Serial.print(" "); 
     checksum = mid + sid;
     Serial.print(checksum);Serial.print(" "); 
     if(mid == NABTON_DATA)
     {
       Serial.print(NFLOAT);Serial.print(" "); 
       NB_printFloat(data,NFLOAT);
     }
     if(mid == NABTON_INFO)
     {
       Serial.print(other); // g_device_delay
     }
     Serial.print(";");
     digitalWrite(PIN_LED_STATUS,LOW);
}
//=================================================
void recSerial()
//=================================================
{
  int i,k=0,ttemp,nx=0,nm=0;
  nx = Serial.available();
  char buffer[50],msg[5][100],command[48];
  int start = 0;
  int dir,steps,vel;
  
  for(i=0;i<5;i++)strcpy(msg[i]," ");
  if (nx > 0) 
  {
     Serial.readBytes(buffer,nx);
     //sprintf(dr[3],"%d",nx);

     for(i=0;i<nx;i++)
     {
       if(buffer[i]==';')
       {
         start = 0;
         msg[nm][k] = '\0';
         //sprintf(dm[nm],"%s",msg[nm]);
         sprintf(dr[2],"%d",nm);
       }
       if(start==1)
       {
         k++;
         //msg[k] = (int)(unsigned char)buffer[i]; 
         msg[nm][k] = buffer[i]; 
       }
       if(buffer[i]=='*')
       {
         start = 1;
         nm++;
       }
     }
  } 
  if(nm > 0)
  {
    strcpy(dm[1],"???");
    for(i=1;i<=nm;i++)
    {
      if(strstr(msg[i],"NBC_REPORT_CONF") != NULL)
      {
        strcpy(dr[3],"RPC");
        NB_sendToGwy(NABTON_INFO,SID1,0.0,g_device_delay);
      }
      if(strstr(msg[i],"NBC_DEVICE_DELAY") != NULL)
      {
        strcpy(dr[3],"DLY");
        sscanf(msg[i],"%s %d",command,&g_device_delay);
        sprintf(dr[1],"%d",g_device_delay);
      }
      if(strstr(msg[i],"NBC_STEPPER_CTRL") != NULL)
      {
        strcpy(dr[3],"SCL");
        sscanf(msg[i],"%s %d %d %d",command,&dir,&steps,&vel);
        if(dir==1)strcpy(dr[4],"STP>");
        if(dir==2)strcpy(dr[4],"STP<");  
        NB_oledDraw();        
        steps = steps*10;
        if(steps > 0 || steps < 1000)
        {
             if(dir == 1) stepCW(steps,vel);
             if(dir == 2) stepCCW(steps,vel);
         }
      }
    }
    strcpy(dr[4],"-");
    NB_oledDraw();
  }
}

//=================================================
void clearOled()
//================================================= 
{
  int i;
  for(i=1;i<=4;i++)
  {
    strcpy(dl[i],"-");
    strcpy(dm[i],"-");
    strcpy(dr[i],"-");
  }
}

//=================================================
void setup()
//================================================= 
{
  int i;
  float tempC;  
  String str;
  Serial.begin(9600);
  NB_serialFlush();
  pinMode(PIN_LED_STATUS, OUTPUT);
  pinMode(DIR, OUTPUT);
  pinMode(STEP, OUTPUT);
  pinMode(SLEEP, OUTPUT);

  // OLED
//=================================================

  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255);     // white
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3);         // max intensity
  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1);         // pixel on
  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255,255,255);
  }
  clearOled();
// One Wire
//=================================================

  sensors.begin();
  nsensors = sensors.getDeviceCount();
  if(nsensors > 0)
  {
    for(i=0;i<nsensors;i++)
    {
      sensors.getAddress(device[i], i);
      sensors.setResolution(device[i], TEMPERATURE_PRECISION);
    }
  }
  //strcpy(dr[2],NC_NAME);
  //strcpy(dm[3],"-");
  //strcpy(dr[3],"-");
  

  sensors.requestTemperatures();
  for(i=1;i<=nsensors;i++)
  {
      tempC = sensors.getTempC(device[i-1]);    
      str = String(tempC);
      str.toCharArray(dl[i],8); 
  }
  g_sids[1] = SID1;
  g_sids[2] = SID2;
  
  sprintf(dr[1],"%d",g_device_delay);
  NB_oledDraw();
  
  NB_sendToGwy(NABTON_INFO,SID1,0.0,g_device_delay);
  //delay(4000);
}

//=================================================
void loop()
//=================================================
{
  int i;
  float tempC;
  String str;
  
    sensors.requestTemperatures();
    for(i=1;i<=nsensors;i++)
    {
      tempC = sensors.getTempC(device[i-1]);    
      str = String(tempC);
      str.toCharArray(dl[i],8); 
      NB_sendToGwy(NABTON_DATA,g_sids[i],tempC,0);
      delay(g_device_delay);  
      recSerial(); 
      NB_oledDraw();
    }
 
}
